package com.enterpriseDigitalPlatform.config;

import com.enterpriseDigitalPlatform.dto.JsonRes;
import com.enterpriseDigitalPlatform.exception.ServiceException;
import com.enterpriseDigitalPlatform.filter.MyFilter;
import com.enterpriseDigitalPlatform.interceptor.MyInterceptor;
import com.enterpriseDigitalPlatform.util.JwtUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.BindException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.util.List;

@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Value("${spring.application.name}")
    private String applicationName;

    @PostConstruct
    public void init() {
        JwtUtil.setApplicationName(applicationName);
    }

    // 解决跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 所以的接口都是可以的
        registry.addMapping("/**")
                // 所有的人都是可以访问的
                .allowedOrigins("*")
                // 所有的头都可以访问
                .allowedHeaders("*")
                // 所有的方法都可以访问
                .allowedMethods("*");
    }

    @Bean
    public FilterRegistrationBean MyFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        // 注入过滤器
        registrationBean.setFilter(new MyFilter());
        // 过滤器名称
        registrationBean.setName("MyFilter");
        // 拦截规则
        registrationBean.addUrlPatterns("/*");
        // 过滤器顺序
        registrationBean.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
        return registrationBean;
    }

    /**
     * 注册拦截器
     * 可以 操作数据库
     * registry
     */
    @Bean
    MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor()).addPathPatterns("/**").excludePathPatterns("/static");
    }


    /**
     * 注册拦截器
     * <p>
     * registry
     */
    // @Override
    // public void addInterceptors(InterceptorRegistry registry) {
    //     registry.addInterceptor(new MyInterceptor())
    //             .addPathPatterns("/**");
    // }

    // 统一异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add((request, response, handler, e) -> {
            JsonRes result = new JsonRes();
            // 异常处理
            if (e instanceof ServiceException) {
                // 1、业务失败的异常，如“账号或密码错误”
                result.setCode(300);
                result.setMsg("错误代码:001 " + e.getMessage());
                log.error(e.getMessage());
            } else if (e instanceof BindException) {
                // 2、参数校验失败
                result.setCode(300);
                result.setMsg("错误代码:002 " + ((BindException) e).getBindingResult().getFieldError().getDefaultMessage());
                log.error(e.getMessage());
            } else if (e instanceof ServletException) {
                // 3、调用失败
                result.setCode(300);
                result.setMsg("错误代码:003 " + e.getMessage());
                log.error(e.getMessage());
            } else {
                // 4、内部其他错误
                result.setCode(300);
                result.setMsg("接口 [" + request.getRequestURI() + "] 内部错误，请联系管理员");
                String message;
                if (handler instanceof HandlerMethod) {
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    message = String.format("接口 [%s] 出现异常，方法：%s.%s，异常摘要：%s",
                            request.getRequestURI(),
                            handlerMethod.getBean().getClass().getName(),
                            handlerMethod.getMethod().getName(),
                            e.getMessage());
                } else {
                    message = e.getMessage();
                }
                result.setMsg("错误代码:004 " + message);
                log.error(e.getMessage());
            }
            responseResult(response, result);
            return new ModelAndView();
        });
    }

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    // 处理响应数据格式
    private void responseResult(HttpServletResponse response, JsonRes result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            // response.getWriter().write(result.getMsg());
            response.setContentType("application/json; charset=UTF-8");
            // 普通json输出
            response.getWriter().write(OBJECT_MAPPER.writeValueAsString(result));
            // 美化json输出
            // OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(result)
            response.getWriter().close();
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }
}